package com.triones.api.service.interlace.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.constant.EmailCodeTypeConstants;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.PushNotificationEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.DateUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.email.EmailValidationUtils;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.triones.api.entity.ApplyVipRecordDO;
import com.triones.api.entity.EmailChangeRecordDO;
import com.triones.api.entity.InviteRecordDO;
import com.triones.api.entity.MemberDO;
import com.triones.api.entity.bo.EmailChangeRecordBO;
import com.triones.api.entity.bo.UpdatePwdBO;
import com.triones.api.entity.interlace.bo.request.ListAllBalancesRequest;
import com.triones.api.entity.interlace.dto.InterlaceBalancesDO;
import com.triones.api.entity.interlace.dto.InterlaceBlockchainAddressCatalogueDO;
import com.triones.api.entity.interlace.dto.InterlaceMemberDO;
import com.triones.api.entity.interlace.vo.CustomInterlaceMemberVO;
import com.triones.api.entity.interlace.vo.InterlaceBalancesVO;
import com.triones.api.entity.interlace.vo.InterlaceBlockchainAddressCatalogueVO;
import com.triones.api.entity.interlace.vo.InterlaceMemberVO;
import com.triones.api.entity.vo.CustomApplyVipRecordVO;
import com.triones.api.entity.vo.CustomInviteRecordVO;
import com.triones.api.mapper.ApplyVipRecordMapper;
import com.triones.api.mapper.EmailChangeRecordMapper;
import com.triones.api.mapper.InviteRecordMapper;
import com.triones.api.mapper.interlace.InterlaceBalancesMapper;
import com.triones.api.mapper.interlace.InterlaceBlockchainAddressCatalogueMapper;
import com.triones.api.mapper.interlace.InterlaceMemberMapper;
import com.triones.api.service.interlace.InterlaceCommunalService;
import com.triones.api.service.interlace.InterlaceMemberService;
import com.triones.api.service.interlace.PushService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * interlace 用户会员相关接口
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class InterlaceMemberServiceImpl implements InterlaceMemberService {

    private final InterlaceMemberMapper interlaceMemberMapper;

    private final InterlaceBlockchainAddressCatalogueMapper interlaceBlockchainAddressCatalogueMapper;

    private final InviteRecordMapper inviteRecordMapper;

    private final ApplyVipRecordMapper applyVipRecordMapper;

    private final EmailChangeRecordMapper emailChangeRecordMapper;

    private final InterlaceBalancesMapper interlaceBalancesMapper;

    private final PushService pushService;

    private final InterlaceCommunalService interlaceCommunalService;

    @Override
    public Boolean checkHaveApplyVip() {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        boolean flag = false;
        InterlaceMemberDO interlaceMemberDO = interlaceMemberMapper.selectById(loginUser.getUserId());
        Long count = inviteRecordMapper.selectCount(new LambdaQueryWrapper<InviteRecordDO>().eq(InviteRecordDO::getUid, loginUser.getUserId())
            .eq(InviteRecordDO::getIsEffective, "1"));
        if (interlaceMemberDO != null) {
            if ("0".equals(interlaceMemberDO.getIsVip()) && count >= 5) {
                flag = true;
            }
        }
        return flag;
    }

    @Override
    public boolean apiApplyVip() {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        if (!this.checkHaveApplyVip()) {
            throw new ServiceException("您当前不具备申请成为白标用户的条件");
        }
        ApplyVipRecordDO applyVipRecordDO = new ApplyVipRecordDO();
        applyVipRecordDO.setUid(loginUser.getUserId());
        applyVipRecordDO.setCreateTime(System.currentTimeMillis());
        return applyVipRecordMapper.insert(applyVipRecordDO) > 0;
    }

    @Override
    public TableDataInfo<InterlaceBlockchainAddressCatalogueVO> blockchainAddressCataloguePageList(String keyword, PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        LambdaQueryWrapper<InterlaceBlockchainAddressCatalogueDO> lqw = new LambdaQueryWrapper<InterlaceBlockchainAddressCatalogueDO>();
        lqw.eq(InterlaceBlockchainAddressCatalogueDO::getUid, loginUser.getUserId())
            .eq(InterlaceBlockchainAddressCatalogueDO::getDel, "0")
            .and(StringUtils.isNotBlank(keyword),
                qr -> qr.like(InterlaceBlockchainAddressCatalogueDO::getNickName, keyword).or()
                    .like(InterlaceBlockchainAddressCatalogueDO::getAddress, keyword).or()
                    .like(InterlaceBlockchainAddressCatalogueDO::getCurrency, keyword).or()
                    .like(InterlaceBlockchainAddressCatalogueDO::getChain, keyword))
            .orderByAsc(InterlaceBlockchainAddressCatalogueDO::getSort)
            .orderByDesc(InterlaceBlockchainAddressCatalogueDO::getCreateTime);
        Page<InterlaceBlockchainAddressCatalogueVO> result = interlaceBlockchainAddressCatalogueMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public boolean addBlockchainAddressCatalogue(InterlaceBlockchainAddressCatalogueDO dto) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        dto.setCreateTime(System.currentTimeMillis());
        dto.setUpdateTime(System.currentTimeMillis());
        dto.setUid(loginUser.getUserId());
        return interlaceBlockchainAddressCatalogueMapper.insert(dto) > 0;
    }

    @Override
    public InterlaceBlockchainAddressCatalogueVO blockchainAddressCatalogueDetail(Long id) {
        return interlaceBlockchainAddressCatalogueMapper.selectVoById(id);
    }

    @Override
    public boolean editBlockchainAddressCatalogue(InterlaceBlockchainAddressCatalogueDO dto) {
        dto.setUpdateTime(System.currentTimeMillis());
        return interlaceBlockchainAddressCatalogueMapper.updateById(dto) > 0;
    }

    @Override
    public boolean removeBlockchainAddressCatalogue(Long id) {
        InterlaceBlockchainAddressCatalogueDO addressCatalogueDO = interlaceBlockchainAddressCatalogueMapper.selectById(id);
        if (addressCatalogueDO == null) {
            throw new SecurityException("常用地址不存在");
        }
        addressCatalogueDO.setDel("1");
        return interlaceBlockchainAddressCatalogueMapper.updateById(addressCatalogueDO) > 0;
    }

    @Override
    public boolean checkNickNameUnique(InterlaceBlockchainAddressCatalogueDO dto) {
        boolean exist = interlaceBlockchainAddressCatalogueMapper.exists(new LambdaQueryWrapper<InterlaceBlockchainAddressCatalogueDO>()
            .eq(InterlaceBlockchainAddressCatalogueDO::getNickName, dto.getNickName())
            .eq(InterlaceBlockchainAddressCatalogueDO::getDel, "0")
            .ne(ObjectUtil.isNotNull(dto.getId()), InterlaceBlockchainAddressCatalogueDO::getId, dto.getId()));
        return !exist;
    }

    @Override
    public TableDataInfo<CustomInviteRecordVO> apiInviteMemberPageList(String isEffective, PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        QueryWrapper<Object> wrapper = Wrappers.query();
        wrapper.eq(StringUtils.isNotBlank(isEffective), "tir.is_effective", isEffective);
        wrapper.eq("tir.uid", loginUser.getUserId());
        wrapper.orderByDesc("tir.create_time");
        Page<CustomInviteRecordVO> result = inviteRecordMapper.interlaceSelectPageList(pageQuery.build(), wrapper);
        return TableDataInfo.build(result);
    }

    @Override
    public boolean updatePwd(UpdatePwdBO bo) {
        InterlaceMemberDO interlaceMemberDO = interlaceMemberMapper.selectOne(new LambdaQueryWrapper<InterlaceMemberDO>()
            .eq(InterlaceMemberDO::getEmail, bo.getEmail())
            .eq(InterlaceMemberDO::getStatus, "0"));
        if (interlaceMemberDO == null) {
            throw new ServiceException("当前用户不存在");
        }
        long timeToLive = RedisUtils.getTimeToLive(EmailCodeTypeConstants.CW_EMAIL_PWD_UPDATE + interlaceMemberDO.getEmail());
        if (timeToLive == -2) {
            throw new ServiceException("验证码已失效");
        }
        String code = Convert.toStr(RedisUtils.getCacheObject(EmailCodeTypeConstants.CW_EMAIL_PWD_UPDATE + interlaceMemberDO.getEmail()), "");
        if (!code.equals(bo.getEmailCode())) {
            throw new ServiceException("验证码错误!");
        }
        if (!bo.getNewPwd().equals(bo.getConfirmPwd())) {
            throw new ServiceException("确认密码有误!");
        }
        interlaceMemberDO.setPassword(BCrypt.hashpw(bo.getConfirmPwd()));

        /** 推送-KYC审核结果通知 */
        String pushType = "pwd_or_security_setting_change";
        PushNotificationEnum notification = PushNotificationEnum.fromPushType(pushType);
        String zhContent = notification.getZhContent();
        String enContent = notification.getEnContent();
        String jaContent = notification.getJaContent();
        pushService.push(pushType, zhContent, enContent, jaContent, interlaceMemberDO.getId());

        return interlaceMemberMapper.updateById(interlaceMemberDO) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean emailRedirect(EmailChangeRecordBO bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        InterlaceMemberDO interlaceMemberDO = interlaceMemberMapper.selectById(loginUser.getUserId());
        if (interlaceMemberDO == null) {
            throw new ServiceException("当前用户不存在");
        }
        if (!BCrypt.checkpw(bo.getPassword(), interlaceMemberDO.getPassword())) {
            throw new ServiceException("密码错误");
        }
        if (!bo.getOldEmail().equals(interlaceMemberDO.getEmail())) {
            throw new ServiceException("当前邮箱与原邮箱不一致");
        }
        if (EmailValidationUtils.isValidEmail(bo.getNewEmail())) {
            throw new RuntimeException("邮箱格式不正确");
        }
        String code = Convert.toStr(RedisUtils.getCacheObject(EmailCodeTypeConstants.CW_EMAIL_CHANGE_CODE + bo.getNewEmail()), "");
        if (!code.equals(bo.getCode())) {
            throw new ServiceException("验证码错误!");
        }
        interlaceMemberDO.setEmail(bo.getNewEmail());

        /** 保存更换邮箱记录 */
        EmailChangeRecordDO emailChangeRecordDO = new EmailChangeRecordDO();
        emailChangeRecordDO.setUid(loginUser.getUserId());
        emailChangeRecordDO.setAfterReplacement(bo.getOldEmail());
        emailChangeRecordDO.setBeforeReplacement(bo.getNewEmail());
        emailChangeRecordDO.setCreateTime(DateUtil.getDateTimeString());
        emailChangeRecordMapper.insert(emailChangeRecordDO);
        return interlaceMemberMapper.updateById(interlaceMemberDO) > 0;
    }

    @Override
    public TableDataInfo<CustomInterlaceMemberVO> pageList(InterlaceMemberDO dto, PageQuery pageQuery) {
        Map<String, Object> params = dto.getParams();
        QueryWrapper<Object> wrapper = Wrappers.query();
        wrapper.ne("tim.id", 1);
        wrapper.like(StringUtils.isNotEmpty(dto.getEmail()), "tim.email", dto.getEmail());
        wrapper.like(StringUtils.isNotEmpty(dto.getNickname()), "tim.nickname", dto.getNickname());
        wrapper.and(StringUtils.isNotEmpty(dto.getFirstName()), qr ->
            qr.like("tim.first_name", dto.getFirstName()).or()
                .like("tim.last_name", dto.getFirstName())
        );
        wrapper.eq(StringUtils.isNotEmpty(dto.getInviteCode()), "tim.invite_code", dto.getInviteCode());
        wrapper.eq(StringUtils.isNotEmpty(dto.getIsVip()), "tim.is_vip", dto.getIsVip());
        wrapper.eq(StringUtils.isNotEmpty(dto.getStatus()), "tim.status", dto.getStatus());
        wrapper.eq(StringUtils.isNotEmpty(dto.getBecomeVipWay()), "tim.become_vip_way", dto.getBecomeVipWay());
        wrapper.between(params.get("beginTime") != null && params.get("endTime") != null,
            "tim.create_time", params.get("beginTime"), params.get("endTime"));
        wrapper.orderByAsc("tim.user_no");
        Page<CustomInterlaceMemberVO> result = interlaceMemberMapper.selectPageList(pageQuery.build(), wrapper);
        return TableDataInfo.build(result);
    }

    @Override
    public CustomInterlaceMemberVO getDetail(Long id) {
        CustomInterlaceMemberVO vo = interlaceMemberMapper.getDetail(id);
        /**
         * 电子钱包
         */
        List<InterlaceBalancesVO> balancesVOList = interlaceBalancesMapper.selectVoList(new LambdaQueryWrapper<InterlaceBalancesDO>()
            .eq(InterlaceBalancesDO::getUid, id)
            .and(qr ->
                qr.eq(InterlaceBalancesDO::getWalletType, "CryptoAsset")
                    .ne(InterlaceBalancesDO::getCurrency, "USD")
                    .or()
                    .eq(InterlaceBalancesDO::getWalletType, "Budget")
                    .eq(InterlaceBalancesDO::getCurrency, "USD")
            ).in(InterlaceBalancesDO::getCurrency, "USDC", "USDT", "USD"));
        vo.setBalances(balancesVOList);
        return vo;
    }

    @Override
    public boolean prohibit(InterlaceMemberDO dto) {
        InterlaceMemberDO interlaceMemberDO = interlaceMemberMapper.selectById(dto.getId());
        if (interlaceMemberDO == null) {
            throw new SecurityException("用户不存在！");
        }
        interlaceMemberDO.setStatus(dto.getStatus());
        return interlaceMemberMapper.updateById(interlaceMemberDO) > 0;
    }

    @Override
    public boolean sysSetVip(InterlaceMemberDO dto) {
        InterlaceMemberDO interlaceMemberDO = interlaceMemberMapper.selectById(dto.getId());
        if (interlaceMemberDO == null) {
            throw new SecurityException("用户不存在！");
        }
        if (interlaceMemberDO.getIsVip().equals("0")) {
            interlaceMemberDO.setIsVip("1");
            interlaceMemberDO.setBecomeVipWay(dto.getBecomeVipWay());
            return interlaceMemberMapper.updateById(interlaceMemberDO) > 0;
        }
        return true;
    }

    @Override
    public TableDataInfo<CustomApplyVipRecordVO> vipApplyPageList(ApplyVipRecordDO dto, PageQuery pageQuery) {
        Map<String, Object> params = dto.getParams();
        QueryWrapper<Object> wrapper = Wrappers.query();
        wrapper.eq(StringUtils.isNotBlank(dto.getAuditStatus()), "avr.audit_status", dto.getAuditStatus());
        wrapper.like(StringUtils.isNotEmpty(Convert.toStr(params.get("beginTime"))), "tim.email", Convert.toStr(params.get("beginTime")));
        wrapper.between(params.get("beginTime") != null && params.get("endTime") != null,
            "avr.create_time", params.get("beginTime"), params.get("endTime"));
        wrapper.orderByAsc("avr.create_time");
        Page<CustomApplyVipRecordVO> result = applyVipRecordMapper.selectPageList(pageQuery.build(), wrapper);
        return TableDataInfo.build(result);
    }

    @Override
    public boolean auditVipApply(ApplyVipRecordDO dto) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        ApplyVipRecordDO applyVipRecordDO = applyVipRecordMapper.selectById(dto.getId());
        if (applyVipRecordDO == null) {
            throw new ServiceException("用户申请记录不存在");
        }
        if ("0".equals(applyVipRecordDO.getAuditStatus())) {
            applyVipRecordDO.setAuditUserId(loginUser.getUserId());
            applyVipRecordDO.setAuditUserName(loginUser.getUsername());
            applyVipRecordDO.setAuditTime(System.currentTimeMillis());
            applyVipRecordDO.setAuditStatus(dto.getAuditStatus());
            applyVipRecordDO.setFailRemark(dto.getFailRemark());
            if ("1".equals(dto.getAuditStatus())) {
                InterlaceMemberDO interlaceMemberDO = interlaceMemberMapper.selectById(applyVipRecordDO.getUid());
                if (interlaceMemberDO != null) {
                    if (interlaceMemberDO.getIsVip().equals("0")) {
                        interlaceMemberDO.setIsVip("1");
                        interlaceMemberDO.setBecomeVipWay("apply");
                        interlaceMemberMapper.updateById(interlaceMemberDO);
                    }
                }
            }
            return applyVipRecordMapper.updateById(applyVipRecordDO) > 0;
        }
        return false;
    }

    @Override
    public List<InterlaceMemberVO> list() {
        LambdaQueryWrapper<InterlaceMemberDO> lqw = Wrappers.lambdaQuery();
        lqw.eq(InterlaceMemberDO::getStatus, "0")
            .ne(InterlaceMemberDO::getId, 1);
        return interlaceMemberMapper.selectVoList(lqw);
    }

    @Override
    public boolean refreshMoney(Long id) {
        InterlaceMemberDO interlaceMemberDO = interlaceMemberMapper.selectById(id);
        if (interlaceMemberDO == null) {
            throw new ServiceException("当前用户不存在");
        }
        /** 更新balance */
        ListAllBalancesRequest balancesRequest = new ListAllBalancesRequest();
        balancesRequest.setAccountId(interlaceMemberDO.getInterlaceAccountId());
        balancesRequest.setLimit("100");
        balancesRequest.setPage("0");
        interlaceCommunalService.updateBalances(balancesRequest);
        return true;
    }
}
